package com.shigen.demo.thread;

class Ticket { //资源类
    private int number = 30;

    /**
     * （1）synchronized是独占锁，加锁和解锁的过程自动进行，易于操作，但不够灵活。
     *     ReentrantLock也是独占锁，加锁和解锁的过程需要手动进行，不易操作，但非常灵活。
     *
     * （2）synchronized可重入，因为加锁和解锁自动进行，不必担心最后是否释放锁；
     *  ReentrantLock也可重入，但加锁和解锁需要手动进行，且次数需一样，否则其他线程无法获得锁。
     *
     * （3）synchronized不可响应中断，一个线程获取不到锁就一直等着；ReentrantLock可以响应中断。
     *
     *  ReentrantLock还可以实现公平锁机制。也就是在锁上等待时间最长的线程将获得锁的使用权。通俗的理解就是谁排队时间最长谁先执行获取锁。
     */
    public synchronized void saleTicket() {
        if (number > 0) {
            System.out.println(Thread.currentThread().getName() + "卖出第" + number-- + "张票，还剩" + number);
        }
    }
}

public class demo01 {
    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.saleTicket();
            }
        }, "A").start();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.saleTicket();
            }
        }, "B").start();
        new Thread(() -> {
            for (int i = 0; i < 40; i++) {
                ticket.saleTicket();
            }
        }, "C").start();
    }
}
